﻿using CJiaBao.Core.Utils;
using Core.Configuration.Api;
using Core.Configuration.Config;
using IconYuan.Api.Services;
using IconYuan.Manager.Markets;
using IconYuan.Manager.Orders;
using IconYuan.Manager.Products;
using IconYuan.Manager.Systems;
using IconYuan.Manager.Users;
using IconYuan.Model.DTO.Orders;
using IconYuan.Model.DTO.Products;
using IconYuan.Model.Entity.Markets;
using IconYuan.Model.Entity.Orders;
using IconYuan.Model.Entity.Products;
using IconYuan.Model.Entity.Systems;
using IconYuan.Model.Entity.Users;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Net;

namespace IconYuan.Api.Controllers.Orders
{
    /// <summary>
    /// 订单结算,提交订单 操作
    /// </summary>
    public class CheckOutController : ApiBase
    {
        static object lockObj = new object();
        readonly GoodsManager goodsSvc;
        readonly SkuManager skuSvc;
        readonly UserManager userSvc;
        readonly UserAddressManager addressSvc;
        readonly UserCouponManager userCouponSvc;
        readonly RegionManager regionSvc;
        readonly OrderManager orderSvc;
        readonly OrderGoodsManager orderGoodsSvc;
        readonly PromotionManager promotionSvc;        
        public CheckOutController()
        {
            goodsSvc = new GoodsManager();
            userSvc = new UserManager();
            addressSvc = new UserAddressManager();
            regionSvc = new RegionManager();
            skuSvc = new SkuManager();
            userCouponSvc = new UserCouponManager();
            orderSvc = new OrderManager();
            orderGoodsSvc = new OrderGoodsManager();
            promotionSvc = new PromotionManager();
        }

        /// <summary>
        /// 待付款订单信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public CheckOrderOut Order(CheckOrderDto model)
        {
            var order = Order(model, 1);
            order.goods.ForEach(x =>
            {
                x.goods_image = $"{GlobalConfig.CdnDomain}{x.goods_image}";
            });
            return order;
        }

        [HttpGet]
        private CheckOrderOut Order(CheckOrderDto model, int showCoupon = 0)
        {
            Vilidate(model);

            var order = new CheckOrderOut();
            var user = userSvc.Get(model.user_id);
            var gradeList = DtoHelper.GetGradeList();
            //获取等级,若过期则还原VIP等级
            var grade = GetCurrentGrade(user, gradeList);
            var gradeExt = JsonHelper.ToObject<GradeExt>(grade.ext) ?? new GradeExt();

            order.user_id = model.user_id;
            order.store_id = GetStoreId();
            order.parent_id = user.parent_id;
            order.shop_id = model.shopId;
            order.delivery_type = model.delivery;
            //订单商品
            order.goods = ToOrderGoods(model);
            order.goods_price = order.goods.Sum(x => x.goods_price * x.buy_count);
            order.pay_price = order.goods_price;
            order.IsUpgradeGoods = GlobalConfig.UpgradeCategoryId.Contains(order.goods[0].category_id.ToString());
            
            //收货地址
            SetExpress(order, user);
            //配送费
            if (model.delivery == 10)
                order.express_price = GetExpressPrice(order.goods, order.lastExtract);

            //等级免单
            var goodsExist = gradeExt.goods_ids.Contains(order.goods[0].goods_id.ToString());
            if (gradeExt.is_first_free == 1 && goodsExist)
            {   //首单免费一份
                var startTime = user.expire_time.AddYears(-1);
                var idList = GlobalConfig.LimitGoodsId.Split(',').Select(x => Convert.ToInt32(x)).ToList();
                var orderList = orderSvc.GetList<OrderGoodsView>(x => idList.Contains(x.goods_id) && x.order_status >= 30 && x.pay_time > startTime);
                if (orderList.Count <= 0)
                {
                    order.grade_money = order.goods[0].goods_price;
                    order.pay_price = order.pay_price - order.goods[0].goods_price;
                }
            }
            else if (gradeExt.is_first_free == 2 && goodsExist)
            {
                //每单免费一份
                order.grade_money = order.goods[0].goods_price;
                order.pay_price = order.pay_price - order.goods[0].goods_price;
            }

            //积分抵扣
            order.points_num = order.goods.Sum(x => x.points_num);
            if (order.points_num > 0)
            {
                order.points_money = order.goods.Sum(x => x.points_money);
                order.pay_price -= order.points_money;
            }
            //促销活动(体验价、买多件满减)
            SetGoodsPromotion(order);
            //消费金抵扣
            SetBalance(order, user);
            //优惠券抵扣 
            SetCoupn(order);
            //等级抵扣 (不能与等级免单同时用)
            if (order.goods[0].is_enable_grade == 1 && order.grade_money <= 0)
            {
                if (grade.equity > 0)
                    order.grade_money = order.pay_price - Math.Floor(order.pay_price * grade.equity) * 0.01m;
                order.pay_price -= order.grade_money;
            }
            //积分赠送
            if (user.expire_time > DateTime.Now)
            {
                //是升级商品时,送等级对应的积分
                if (order.IsUpgradeGoods)
                {
                    var grade_id = int.Parse(order.goods[0].goods_no);
                    var upGrade = gradeList.Find(x => x.grade_id == grade_id) ?? new UserGrade();
                    gradeExt = JsonHelper.ToObject<GradeExt>(upGrade.ext) ?? new GradeExt();
                    order.points_gift = gradeExt.points;
                }
                else
                {
                    order.points_gift = (int)order.pay_price * gradeExt.order_points_ratio;
                }
            }
            //实付金额
            order.pay_price += order.express_price;
            order.order_price = order.goods_price + order.express_price;
            return order;
        }

        /// <summary>
        /// 创建商品订单,返回订单id(客户端用订单id，调用服务器支付接口)
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public object Submit([FromBody] CheckOrderDto model)
        {
            Vilidate(model);
            lock (lockObj)
            {
                var chkOrder = Order(model, 0);
                var order = OrdersServices.ToOrder(chkOrder, chkOrder.lastExtract);

                //创建订单
                order.order_id = orderSvc.Insert(order);
                if (order.order_id <= 0) throw new Exception("订单创建失败");

                //创建订单商品
                chkOrder.goods.ForEach(x =>
                {
                    x.order_id = order.order_id;
                });
                orderGoodsSvc.InsertRange(chkOrder.goods);

                //返回订单id
                return new { orderId = order.order_id };
            }            
        }

        /// <summary>
        /// 创建升级订单,返回订单id(客户端用订单id，调用服务器支付接口)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public object SubmitUpgrade([FromBody] CheckOrderDto model)
        {
            Vilidate(model);
            lock (lockObj)
            {
                var gradeList = DtoHelper.GetGradeList();
                var user = userSvc.Get(x => x.user_id == model.user_id);
                //不是默认等级时，需过期后再升级   //2024-05-13 去掉续费的限制
                //if (user.grade_id != gradeList.First().grade_id && user.expire_time > DateTime.Now)
                //    throw new Exception("您已经是VIP了");

                //订单商品
                var goods_list = ToOrderGoods(model);
                var goods = goods_list.First();
                var order = ToOrder(goods_list, model, 2);
                order.is_settled = user.parent_id > 0 && order.pay_price > 0 ? 0 : 2;  //有上级才需要分佣
                //创建订单
                order.order_id = orderSvc.Insert(order);
                if (order.order_id <= 1) throw new Exception("创建订单失败");

                goods.order_id = order.order_id;
                orderGoodsSvc.Insert(goods);
                //返回订单id
                return new { orderId = order.order_id };
            }
        }

        /// <summary>
        /// 创建兑换订单
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public object SubmitExchange(CheckOrderDto model)
        {
            Vilidate(model);
            lock (lockObj)
            {
                //订单商品
                var goods_list = ToOrderGoods(model);
                var order = ToOrder(goods_list, model, 3);
                var user = userSvc.Get(x => x.user_id == model.user_id);

                if (user.points < goods_list.Sum(x => x.points_num)) throw new Exception("您的积分不足");
                order.is_settled = user.parent_id > 0 && order.pay_price > 0 ? 0 : 1;
                //创建订单
                order.order_id = orderSvc.Insert(order);
                if (order.order_id <= 1) throw new Exception("创建订单失败");

                var goods = goods_list.First();
                goods.order_id = order.order_id;
                orderGoodsSvc.Insert(goods);
                //返回订单id
                return new { orderId = order.order_id };
            }
        }

        /// <summary>
        /// 验证是否符合条件 (code=200 符合条件, code其他值表示不符合条件，并返回原因)
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public string SubmitCheck(SubmitCheckDto model)
        {
            //是否存在正在进行的订单
            if (model.checktype == 1)
            {
                var idList = GlobalConfig.LimitGoodsId.Split(',').Select(x => Convert.ToInt32(x)).ToList();
                if (idList.Contains(model.goods_id))
                {
                    var oldList = orderSvc.GetList<OrderGoodsView>(x => x.user_id == model.user_id && idList.Contains(x.goods_id) && x.order_status >= 30 && x.order_status < 70);
                    if (oldList.Count > 0) throw new Exception("请先完成正在进行中的疗程");
                }
            }
            //2024-05-13 已去掉VIP续费验证
            //if (model.checktype == 2)
            //{
            //    var user = userSvc.Get(model.user_id);
            //    var gradeList = DtoHelper.GetGradeList();
            //    var defaultGrade = gradeList.Find(x => x.is_default == 1) ?? new UserGrade() { grade_id = user.grade_id };
            //    if (user.grade_id != defaultGrade.grade_id && user.expire_time > DateTime.Now) throw new Exception("您已经是VIP了");
            //}
            return "success";
        }

        #region 私有

        /// <summary>
        /// 计算配送费
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        private decimal GetExpressPrice(List<OrderGoods> goodsList, UserAddress address)
        {
            //商品重量
            int weight = 0;
            return 0;
        }

        /// <summary>
        /// 商品转换成订单商品
        /// </summary>
        private List<OrderGoods> ToOrderGoods(CheckOrderDto model)
        {
            var goods = goodsSvc.Get(model.goodsId);
            if (goods == null) throw new Exception("商品不存在");
            if (goods.status != 10) throw new Exception("商品已下架");
            if (goods.stock_total <= model.buyCount) throw new Exception("商品库存不足");
            if (goods.spec_type == 20 && string.IsNullOrEmpty(model.goodsSkuId)) throw new Exception("请选择商品规格");

            var orderGoods = new OrderGoods()
            {
                user_id = model.user_id,
                goods_id = goods.goods_id,
                goods_no = goods.goods_no,
                goods_name = goods.goods_name,
                goods_sku_id = model.goodsSkuId,
                goods_image = goods.goods_image,
                price_desc = goods.price_desc,
                goods_price = goods.goods_price_min,    //非SKU商品价格
                line_price = goods.line_price_min,

                spec_type = goods.spec_type,
                goods_props = string.Empty,
                goods_weight = 0,   //重量
                deduct_stock_type = goods.deduct_stock_type,
                buy_count = model.buyCount,
                create_time = DateTime.Now,
                category_id = goods.category_id
            };
            //sku价格
            if (!string.IsNullOrEmpty(model.goodsSkuId))
            {
                var sku = skuSvc.GetSingle<Sku>(x => x.goods_id == model.goodsId && x.goods_sku_id == model.goodsSkuId);
                if (sku == null) throw new Exception("规格不存在");
                if (sku.stock_num <= model.buyCount) throw new Exception("此规格库存不足");

                //sku规格
                var goods_prop = sku.goods_props?.ToString() ?? string.Empty;
                if (!string.IsNullOrEmpty(goods_prop))
                    sku.goods_props = JsonHelper.ToObject<List<SkuSpecDto>>(goods_prop);

                orderGoods.skuInfo = sku;
                orderGoods.goods_props = goods_prop;
                orderGoods.goods_price = sku.goods_price;
                orderGoods.goods_weight = sku.goods_weight;
            }
            //设置了积分抵扣
            orderGoods.points_num = goods.points * model.buyCount;
            orderGoods.points_money = orderGoods.goods_price * model.buyCount;
            //设置了等级抵扣
            orderGoods.is_enable_grade = goods.is_enable_grade;
            //实付金额
            orderGoods.pay_price = (orderGoods.goods_price * orderGoods.buy_count) - orderGoods.coupon_money - orderGoods.points_money;
            return new List<OrderGoods> { orderGoods };
        }

        private Order ToOrder(List<OrderGoods> goods_list, CheckOrderDto model, int jump)
        {
            var order = new Order();
            order.jump = jump;
            order.order_no = OrdersServices.GenerateOrderNo();
            order.store_id = GetStoreId();
            order.user_id = model.user_id;
            order.shop_id = model.shopId;
            order.delivery_type = model.delivery;
            order.shop_id = model.shopId;
            order.create_time = DateTime.Now;
            order.pay_time = Convert.ToDateTime("1970-01-01");
            order.express_time = order.pay_time;
            order.order_status = 20;
            order.goods_price = goods_list.Sum(x => x.goods_price * x.buy_count);
            order.order_price = order.goods_price + order.express_price;
            order.points_num = goods_list.Sum(x => x.points_num);
            if (jump == 3)
            {
                order.points_money = order.order_price;
            }
            //实付金额
            order.pay_price = order.order_price - order.points_money;
            return order;
        }

        /// <summary>
        /// 设置商品促销
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        private bool SetGoodsPromotion(CheckOrderOut order)
        {
            if (order.goods.Count <= 0 || order.pay_price <= 0 || order.IsUpgradeGoods) return false;
            var goods_ids = order.goods.Select(x => x.goods_id);

            var promotion = GetPromotion(order.store_id, goods_ids);
            if (promotion == null) return false;
            
            //单品促销, 例如：体验价
            if (promotion.type == 1 && !string.IsNullOrEmpty(promotion.ext))
            {
                //已购买的订单
                var oldList = orderSvc.GetList<OrderGoodsView>(x => x.user_id == order.user_id && x.order_status >= 30 && goods_ids.Contains(x.goods_id));

                var ext = JsonHelper.ToObject<SinglePromotion>(promotion.ext) ?? new SinglePromotion();
                var extGoodsIds = ext.goods_ids.Split(',');
                foreach (var goods in order.goods)
                {
                    //商品不在范围内
                    if (!extGoodsIds.Contains(goods.goods_id.ToString())) continue;
                    //if (!ext.goods_ids.Contains(goods.goods_id.ToString())) continue;
                    //超过购买数量
                    var max_count = oldList.Where(x => x.goods_id == goods.goods_id).Sum(x => x.buy_count);
                    if (max_count >= ext.max_count) continue;

                    if (ext.type == 1)          //一口价
                    {
                        goods.promotion_money = (goods.goods_price - ext.type_value);
                    }
                    //else if (ext.type == 2)     //第二件起减多少
                    //{
                    //    if (goods.buy_count > 1)
                    //        goods.promotion_money = goods.goods_price + ext.type_value * (goods.buy_count - 1);
                    //}
                    else if (ext.type == 3)     //单价打几折
                    {
                        goods.promotion_money = goods.goods_price - Math.Floor(goods.goods_price * goods.buy_count * ext.type_value) * 0.01m;
                    }
                    goods.promotion_id = promotion.promotion_id;
                    order.promotion_money += goods.promotion_money;
                    order.pay_price -= goods.promotion_money;
                    order.promotion_type = promotion.type;
                }
            }

            //满减促销, 例如：买多件优惠
            if (promotion.type == 2 && !string.IsNullOrEmpty(promotion.ext))
            {
                var ext = JsonHelper.ToObject<FullPromotion>(promotion.ext) ?? new FullPromotion();
                var extGoodsIds = ext.goods_ids.Split(',');
                //已购买的订单
                var oldList = orderSvc.GetList<OrderGoodsView>(x => x.user_id == order.user_id && x.order_status >= 30 && goods_ids.Contains(x.goods_id));

                //总价满多少减多少
                if (ext.type == 1)
                {
                    var total_price = order.goods.Sum(x => x.goods_price * x.buy_count);
                    if (total_price >= ext.secend_limit)        //第二次门槛
                    {
                        order.promotion_id = promotion.promotion_id;
                        order.promotion_money = ext.secend_cut;
                    }
                    else if (total_price >= ext.first_limit)     //第一次门槛
                    {
                        order.promotion_id = promotion.promotion_id;
                        order.promotion_money = ext.first_cut;
                    }
                }
                //买几件单价减多少
                if (ext.type == 2)
                {
                    foreach (var goods in order.goods)
                    {
                        //商品不在范围内
                        if (!extGoodsIds.Contains(goods.goods_id.ToString())) continue;
                        //if (!ext.goods_ids.Contains(goods.goods_id.ToString())) continue;
                       
                        //历史购买数量
                        var old_count = oldList.Where(x => x.goods_id == goods.goods_id).Sum(x => x.buy_count);
      
                        //第二次门槛
                        if (goods.buy_count >= ext.secend_limit && goods.buy_count + old_count < ext.max_count)
                        {
                            order.promotion_id = promotion.promotion_id;
                            order.promotion_money += ext.secend_cut * goods.buy_count;
                            order.promotion_type = promotion.type;
                        }
                        //第一次门槛
                        else if (goods.buy_count >= ext.first_limit && goods.buy_count + old_count < ext.max_count)
                        {
                            order.promotion_id = promotion.promotion_id;
                            order.promotion_money += ext.first_cut * goods.buy_count;
                            order.promotion_type = promotion.type;
                        }                       
                    }
                }
                order.pay_price -= order.promotion_money;
            }
            return true;
        }
       

        //余额抵扣
        private void SetBalance(CheckOrderOut order,User user)
        {
            if (order.IsUpgradeGoods) return;

            if (user.balance > order.pay_price)
                order.balance_money = order.pay_price;
            else
                order.balance_money = user.balance;

            order.pay_price -= order.balance_money;
        }

        //优惠券抵扣(取最大优惠的券)
        private void SetCoupn(CheckOrderOut order)
        {
            if (order.pay_price <= 0 || order.IsUpgradeGoods) return;

            var date = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd"));
            order.couponList = userCouponSvc.GetList(x => x.is_use == 0 && x.user_id == order.user_id && date > x.start_time && x.end_time >= date, y => y.user_coupon_id, OrderByType.Asc);
           
            foreach (var coupon in order.couponList)
            {
                var errMsg = OrdersServices.CheckCoupon(coupon, order.goods);
                if (!string.IsNullOrEmpty(errMsg)) continue;

                var coupon_money = 0m;
                if (order.pay_price >= coupon.min_price)
                {
                    if (coupon.coupon_type == 20)               //满多少减多少
                        coupon_money = Math.Floor(order.pay_price * coupon.discount) * 0.01m;
                    else
                        coupon_money = coupon.reduce_price;     //折扣多少
                }
                //取最大优惠的券
                if (coupon_money > order.coupon_money)
                {
                    order.coupon_id = coupon.user_coupon_id;
                    order.coupon_money = coupon_money;
                }
            }
            order.pay_price -= order.coupon_money;
        }

        //收货地址
        private void SetExpress(CheckOrderOut order, User user)
        {
            if (order.delivery_type == 10 && user.address_id > 0)
            {
                var addressInfo = addressSvc.Get(user.address_id) ?? new UserAddress();
                if (addressInfo.address_id > 0)
                {
                    var region = regionSvc.Get(addressInfo.region_id) ?? new Region();
                    order.address = $"{region.city}{region.name}{addressInfo.detail}";
                }
                order.lastExtract = addressInfo;
                order.express_price = 0;
            }
        }
        /// <summary>
        /// 获取权重最大的促销
        /// </summary>
        /// <param name="store_id"></param>
        /// <param name="goodsIds"></param>
        /// <returns></returns>
        private Promotion GetPromotion(int store_id, IEnumerable<int> goodsIds)
        {
            //获取权重最大的促销
            var promotionList = promotionSvc.GetList(x => x.store_id == store_id && x.status == 1, y => y.weight, OrderByType.Desc);
            var goods_ids = string.Join(",", goodsIds);
            foreach (var promotion in promotionList)
            {
                if (promotion.type == 1)
                {
                    var ext = JsonHelper.ToObject<SinglePromotion>(promotion.ext);
                    if (ext != null && ext.goods_ids.Contains(goods_ids))
                        return promotion;
                }
                else if (promotion.type == 2)
                {
                    var ext = JsonHelper.ToObject<FullPromotion>(promotion.ext) ?? new FullPromotion();
                    if (ext != null && ext.goods_ids.Contains(goods_ids))
                        return promotion;
                }
                else if (promotion.type == 3)
                {
                    var ext = JsonHelper.ToObject<FullPromotion>(promotion.ext) ?? new FullPromotion();
                    if (ext != null && ext.goods_ids.Contains(goods_ids))
                        return promotion;
                }
            }
            return null;
        }
        /// <summary>
        /// 用户等级
        /// </summary>
        private UserGrade GetCurrentGrade(User user,List<UserGrade> gradeList)
        {
            if (user.expire_time <= DateTime.Now)
            {
                //如果VIP到期，自动恢复成默认VIP等级
                var grade = gradeList.Find(x => x.is_default == 1);
                userSvc.Update(x => new User { grade_id = grade.grade_id, expire_time = DateTime.Now.AddYears(10) }, y => y.user_id == user.user_id);
                user.grade_id = grade.grade_id; //刷新用户等级ID
                return grade;
            }
            return gradeList.Find(x => x.grade_id == user.grade_id) ?? new UserGrade();
        }
        private void Vilidate(CheckOrderDto model)
        {
            if (model.user_id <= 0) throw new WebException("请先登录");
            if (model.buyCount < 1) throw new Exception("请选择购买数量");
            if (model.delivery == 10 && model.goodsId < 1) throw new Exception("请选择商品");
        }

        #endregion
    }
}
